package com.aca.market.service.impl;

import com.aca.market.entity.Indent;
import com.aca.market.entity.IndentItem;
import com.aca.market.entity.Storage;
import com.aca.market.entity.User;
import com.aca.market.mapper.*;
import com.aca.market.service.IIndentItemService;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.stream.Collectors;

@Slf4j
@Service
@Transactional
public class IIndentItemServiceImpl extends ServiceImpl<IndentItemMapper, IndentItem>
        implements IIndentItemService{

    @Autowired
    IndentMapper indentMapper;
    @Autowired
    UserMapper userMapper;
    @Autowired
    CatalogMapper catalogMapper;
    @Autowired
    StorageMapper storageMapper;
    @Autowired
    IndentItemMapper iiMapper;


    @Override
    public IPage<IndentItem> selectPage(Page<IndentItem> page, Wrapper<IndentItem> queryWrapper){
        return iiMapper.selectPage(page,queryWrapper);
    }

    @Override
    //单个分类下所有商品的销售情况
    public List<IndentItem> getTypeItemSale(List<Long> typeIdList,Boolean salesDesc){
        List<IndentItem> typeItems = iiMapper.selectList(new QueryWrapper<IndentItem>()
                .in("item_type", typeIdList));
        //用IndentItem当viewObject
        Map<Long,IndentItem> map = new HashMap<>(typeItems.size());
        //销售数量
        Integer count = 0;
        //销售额
        BigDecimal in = BigDecimal.ZERO;
        //最近销售时间
        LocalDateTime newTime = LocalDateTime.MAX;
        for (IndentItem typeItem : typeItems) {
            IndentItem tmp = typeItem;
            if (map.containsKey(typeItem.getItemType())){
                count += typeItem.getCount();
                in = in.add(typeItem.getPriceSell());
                newTime = newTime.isAfter(typeItem.getUpdateTime()) ? typeItem.getUpdateTime():newTime;
                tmp.setPriceSell(in).setCount(count).setUpdateTime(newTime);
                map.put(typeItem.getItemType(),tmp);
            }else {
                map.putIfAbsent(typeItem.getItemType(),tmp);
            }
        }
        List<IndentItem> res = new ArrayList<IndentItem>(){{addAll(map.values());}};
        if (salesDesc) {
            Collections.sort(res, Comparator.comparingInt(IndentItem::getCount).reversed());
        }
        log.info("======>getTypeItemSale: {}",map);
        return res;
    }

    @Override
    //销量排行（名字：销量映射表）
    public ConcurrentMap<String, Integer> getBestSellerItem(){
        ConcurrentMap<String, Integer> bestSellerItems = new ConcurrentHashMap<>();
        List<Storage> storages = storageMapper.selectList(new QueryWrapper<Storage>()
                .select("item_name", "sales").orderByDesc("sales"));
        storages.parallelStream().forEach((storage -> bestSellerItems.putIfAbsent(storage.getItemName(),storage.getSales())));
        return bestSellerItems;
    }

    @Override
    public BigDecimal getMonthPurchaseCost(){
        //成本
        return storageMapper.selectList(new QueryWrapper<Storage>()
                .between("update_time", LocalDateTime.now().minusMonths(1L), LocalDateTime.now()))
                .parallelStream()
                .map(Storage::getPriceIn)
                .reduce(BigDecimal.ZERO,BigDecimal::add);
    }

    @Override
    //月净利润
    public BigDecimal getMonthNetProfile(){
        BigDecimal res = BigDecimal.ZERO;
        //总
        List<IndentItem> sales = iiMapper.selectList(new QueryWrapper<IndentItem>()
                .between("create_time", LocalDateTime.now().minusMonths(1L), LocalDateTime.now()));
        for (IndentItem sale : sales) {
            res = res.add(sale.getPriceSell());
        }
        List<Long> itemIdList = sales.parallelStream().mapToLong(IndentItem::getItemId)
                .boxed().collect(Collectors.toList());
        //成本
        List<Storage> storageList = storageMapper.selectList(new QueryWrapper<Storage>()
                .in("item_id",itemIdList)
                .select("price_in"));
        for (Storage storage : storageList) {
            res = res.subtract(storage.getPriceIn());
        }
        log.info("月净利润===>"+res);
        return res;
    }

    @Override
    public BigDecimal getMonthProfit() {
        return indentMapper.selectList(new QueryWrapper<Indent>()
                .between("create_time", LocalDateTime.now().minusMonths(1L), LocalDateTime.now()))
                .parallelStream().map(Indent::getPayment).reduce(BigDecimal.ZERO,BigDecimal::add);
    }

    @Override
    public BigDecimal getLoss(){
        return getMonthProfit().subtract(getMonthNetProfile()).subtract(getMonthPurchaseCost());
    }

    @Override
    public Integer getIndentsCount(){
        return indentMapper.selectCount(new QueryWrapper<Indent>().isNotNull("create_time"));
    }

    @Override
    public Integer getUsersCount(){
        return userMapper.selectCount(new QueryWrapper<User>().notIn("verified","N"));
    }

}
